#ifndef FCAN_SIMPLE_H
#define FCAN_SIMPLE_H

#include <stdint.h>
#include <stdbool.h>
#include "ftypes.h"
#include "fswap.h"
#include "fkernel.h"
#include "fio.h"

#define FT_COMPONENT_IS_READY 0x11111111U
#define FT_COMPONENT_IS_STARTED 0x22222222U
#define BIT(nr) (1U << (nr))

#define FCAN_READ_REG32(addr, reg_offset) FtIn32((addr) + (u32)(reg_offset))
#define FCAN_WRITE_REG32(addr, reg_offset, reg_value) FtOut32((addr) + (u32)reg_offset, (u32)reg_value)

/* FCAN_FIFO_CNT_OFFSET mask */
#define FCAN_FIFO_CNT_RFN_MASK       GENMASK(6, 0)    /*Receive FIFO valid data number*/
#define FCAN_FIFO_CNT_RFN_GET(x)     GET_REG32_BITS((x), 6, 0)
#define FCAN_FIFO_CNT_RFN_SET(x)     SET_REG32_BITS((x), 6, 0)

#define FCAN_FIFO_CNT_TFN_MASK       GENMASK(6, 0)    /*Transmit FIFO valid data number*/
#define FCAN_FIFO_CNT_TFN_GET(x)     GET_REG32_BITS((x), 22, 16)
#define FCAN_FIFO_CNT_TFN_SET(x)     SET_REG32_BITS((x), 22, 16)

#define FCAN_RX_FIFO_EMPTY(base_addr) (0 == FCAN_FIFO_CNT_RFN_GET(FCAN_READ_REG32(base_addr, FCAN_FIFO_CNT_OFFSET)))
#define FCAN_TX_FIFO_FULL(base_addr) ((CAN_FIFO_BYTE_LEN) - (4 * (FCAN_FIFO_CNT_TFN_GET(FCAN_READ_REG32(base_addr, FCAN_FIFO_CNT_OFFSET)))) < KEEP_CAN_FIFO_MIN_LEN)
#define FCANFD_TX_FIFO_FULL(base_addr) ((CAN_FIFO_BYTE_LEN) - (4 * (FCAN_FIFO_CNT_TFN_GET(FCAN_READ_REG32(base_addr, FCAN_FIFO_CNT_OFFSET)))) < KEEP_CANFD_FIFO_MIN_LEN)

#define FCAN_SUCCESS      0
#define FCAN_FAILURE      -1
#define FCAN_INVAL_PARAM  -2

#define FCAN_DATA_LENGTH 64U

#define CAN_EFF_FLAG 0x80000000U
#define CAN_RTR_FLAG 0x40000000U
#define CAN_SFF_MASK 0x000007FFU
#define CAN_EFF_MASK 0x1FFFFFFFU

#define CANFD_BRS 0x02
#define CANFD_ESI 0x04

#define FCAN_CTRL_XFER_MASK     BIT(0)   /*Transfer enable*/
#define FCAN_CTRL_TXREQ_MASK    BIT(1)   /*Transmit request*/

#define FCAN_CTRL_IOF_MASK      BIT(10)  /* send overload frame */
#define FCAN_CTRL_FDCRC_MASK    BIT(11)  /* Stuff count, crc mode */
#define FCAN_CTRL_RST_MASK      BIT(7)   /* Soft rest 1:reset and auto clear */
//#define FCAN_CLK_FREQ_HZ 600000000

#define FCAN_ARB_TSEG1_MIN  1
#define FCAN_ARB_TSEG1_MAX  16
#define FCAN_ARB_TSEG2_MIN  1
#define FCAN_ARB_TSEG2_MAX  8
#define FCAN_ARB_SJW_MAX    4
#define FCAN_ARB_BRP_MIN    1
#define FCAN_ARB_BRP_MAX    512
#define FCAN_ARB_BRP_INC    1
#define FCAN_DATA_TSEG1_MIN 1
#define FCAN_DATA_TSEG1_MAX 16
#define FCAN_DATA_TSEG2_MIN 1
#define FCAN_DATA_TSEG2_MAX 8
#define FCAN_DATA_SJW_MAX   4
#define FCAN_DATA_BRP_MIN   1
#define FCAN_DATA_BRP_MAX   512
#define FCAN_DATA_BRP_INC   1
#define FCAN_REG_LENGTH 0x1000
//#define FCAN0_BASE_ADDR 0x28207000
//#define FCAN0_BASE_ADDR 0x28000000
//#define FCAN1_BASE_ADDR 0x40000000
#define FCAN_FD_CAPACITY    BIT(0)   /* Whether canfd is supported */
//#define FCAN_CAPACITY       1
#define CAN_CALC_MAX_ERROR  50 /* in one-tenth of a percent */
#define CAN_CALC_SYNC_SEG   1

/***ft CAN REGISTER offset*/
#define FCAN_CTRL_OFFSET            0x00 /* Global control register */
#define FCAN_ARB_RATE_CTRL_OFFSET   0x08 /* Arbitration rate control register */
#define FCAN_DAT_RATE_CTRL_OFFSET   0x0C /* Data rate control register */
#define FCAN_ACC_ID0_OFFSET         0x10 /* Acceptance identifier0 register */
#define FCAN_ACC_ID1_OFFSET         0x14 /* Acceptance identifier1 register */
#define FCAN_ACC_ID2_OFFSET         0x18 /* Acceptance identifier2 register */
#define FCAN_ACC_ID3_OFFSET         0x1C /* Acceptance identifier3 register */
#define FCAN_ACC_ID0_MASK_OFFSET    0x20 /* Acceptance identifier0 mask register */
#define FCAN_ACC_ID1_MASK_OFFSET    0x24 /* Acceptance identifier1 mask register */
#define FCAN_ACC_ID2_MASK_OFFSET    0x28 /* Acceptance identifier2 mask register */
#define FCAN_ACC_ID3_MASK_OFFSET    0x2C /* Acceptance identifier3 mask register */
#define FCAN_XFER_STS_OFFSET        0x30 /* Transfer status register */
#define FCAN_ERR_CNT_OFFSET         0x34 /* Error counter register */
#define FCAN_FIFO_CNT_OFFSET        0x38 /* FIFO counter register */
#define FCAN_DMA_CTRL_OFFSET        0x3C /* DMA request control register */
#define FCAN_XFER_EN_OFFSET         0x40 /* Transfer enable register */
#define FCAN_FRM_INFO_OFFSET        0x48 /* Frame valid number register */
#define FCAN_TX_FIFO_OFFSET         0x100/* TX FIFO shadow register */
#define FCAN_RX_FIFO_OFFSET         0x200/* RX FIFO shadow register */
#define FCAN_RX_INFO_FIFO_OFFSET    0X300/* Current frame status register */

/*----------------------------------------------------------------------------*/
/* CAN register bit masks - FCAN_<REG>_<BIT>_MASK                            */
/*----------------------------------------------------------------------------*/

#define GET_REG32_BITS(x, a, b)                  (u32)((((u32)(x)) & GENMASK(a, b)) >> b)
#define SET_REG32_BITS(x, a, b)                  (u32)((((u32)(x)) << b) & GENMASK(a, b))

/* FCAN_CTRL mask */
#define FCAN_CTRL_XFER_MASK     BIT(0)   /*Transfer enable*/
#define FCAN_CTRL_TXREQ_MASK    BIT(1)   /*Transmit request*/
#define FCAN_CTRL_AIME_MASK     BIT(2)   /*Acceptance identifier mask enable*/
#define FCAN_CTRL_RST_MASK      BIT(7)   /* Soft rest 1:reset and auto clear */
#define FCAN_CTRL_RFEIDF_MASK   BIT(8)   /* whether generates frame recv completion interrupt when filtering frames */
#define FCAN_CTRL_IRFEDT_MASK   BIT(9)   /* whether generates frame recv completion interrupt when sending frame */
#define FCAN_CTRL_IOF_MASK      BIT(10)  /* send overload frame */
#define FCAN_CTRL_FDCRC_MASK    BIT(11)  /* Stuff count, crc mode */

/* canfd */
#define FTCANFD_ID1_FDL_MASK    BIT(18)     /* CANFD Standard FDF */
#define FTCANFD_ID1_BRS_MASK    BIT(16)     /* CANFD Standard BRS */
#define FTCANFD_ID1_ESI_MASK    BIT(15)     /* CANFD Standard ESI */
#define FTCANFD_ID1_SDLC_GET(x)   GET_REG32_BITS((x),14, 11)  /* CANFD Standard msg dlc */
#define FTCANFD_IDR_PAD_MASK    GENMASK(10, 0)  /* CANFD Standard msg padding 1 */

#define FTCANFD_ID2_FDL_MASK    BIT(31)  /* CANFD Extended FDF */
#define FTCANFD_ID2_BRS_MASK    BIT(29)  /* CANFD Extended BRS */
#define FTCANFD_ID2_ESI_MASK    BIT(28)  /* CANFD Extended ESI */
#define FTCANFD_ID2_EDLC_GET(x)    GET_REG32_BITS((x), 27, 24)  /* CANFD Extended msg dlc */

#define FCAN_IDR_ID1_SHIFT          21 /* Standard Message Identifier */
#define FCAN_IDR_SDLC_SHIFT         14
#define FCANFD_IDR_EDLC_SHIFT       24
#define FCAN_IDR_EDLC_SHIFT         26
#define FCAN_ACC_IDN_SHIFT          18 /*Standard ACC ID shift*/
#define FCANFD_IDR_GET_EDLC_SHIFT   12
#define FCANFD_IDR1_SDLC_SHIFT      11

/* can */
#define FCAN_IDR_ID2_GET(x)   GET_REG32_BITS((x), 18, 1)  /* Get extended message ident */
#define FCAN_IDR_ID2_SET(x)   SET_REG32_BITS((x), 18, 1)  /* Set extended message ident */
#define FCAN_IDR_ID1_GET(x)   GET_REG32_BITS((x), 31, 21)  /* Get standard msg identifier */
#define FCAN_IDR_ID1_SET(x)   SET_REG32_BITS((x), 31, 21)  /* Set standard msg identifier */
#define FCAN_IDR_IDE_MASK   BIT(19)     /* Identifier extension */
#define FCAN_IDR_SRR_MASK   BIT(20)  /* Substitute remote TXreq */
#define FCAN_IDR_RTR_MASK   BIT(0)  /* Extended frames remote TX request */
#define FCAN_IDR_PAD_MASK   GENMASK(13, 0)  /* Standard msg padding 1 */
#define FCAN_IDR_DLC_GET(x)   GET_REG32_BITS((x), 17, 14)  /* Standard msg dlc */
#define FCAN_IDR_EDLC_GET(x)  GET_REG32_BITS((x), 29, 26)  /* Extended msg dlc */
#define FCAN_ACC_IDN_MASK           GENMASK(28, 0)/*don’t care the matching */
#define FCAN_ACC_ID_REG_NUM         4

#define STANDARD_FRAME  0   /* standard frame */
#define EXTEND_FRAME    1   /* extended frame */

#define FCAN_STANDARD_FRAME     0
#define FCAN_EXTENDARD_FRAME    1

#define  FCAN0_ID  0
#define  FCAN1_ID  1
#define  FCAN_NUM  2

typedef u32 FError;

typedef enum {
    FCAN_ARB_SEGMENT = 0,
    FCAN_DATA_SEGMENT = 1
} FCanSegmentType;

typedef struct {
    uint32_t canid;
    uint8_t candlc;
    uint8_t flags;
    uint8_t data[FCAN_DATA_LENGTH];
} FCanFrame;

typedef struct
{
    u32 instance_id;   /* Id of device */
    uintptr base_address; /* Can base Address */
    u32 caps;
} FCanConfig;

typedef struct {
    FCanSegmentType segment;
    bool auto_calc;
    uint32_t baudrate;
    uint32_t sample_point;
    uint32_t prop_seg;
    uint32_t phase_seg1;
    uint32_t phase_seg2;
    uint32_t sjw;
    uint32_t brp;
} FCanBaudrateConfig;

typedef struct
{
    FCanConfig config;
    u32 is_ready;  /* Device is initialized and ready */
    boolean use_canfd; /* if use canfd function */
} FCanCtrl;

typedef struct
{
    u32 filter_index;/* filter register index*/
    u32 id; /* id bit to receive */
    u32 mask;/* id mask bit to receive */
    u32 type;/* frame type, standard or extended*/
} FCanIdMaskConfig;

// 函数声明
FError FCanCfgInitialize(FCanCtrl *instance_p, const FCanConfig *input_config_p);
FError FCanBaudrateSet(FCanCtrl *instance_p, FCanBaudrateConfig *baudrate_p);
FError FCanSend(FCanCtrl *instance_p, FCanFrame *frame_p);
FError FCanRecv(FCanCtrl *instance_p, FCanFrame *frame_p);
FError FCanFdEnable(FCanCtrl *instance_p, boolean enable);
FError FCanEnable(FCanCtrl *instance_p, boolean enable);
FError FCanSetMode(FCanCtrl *instance_p , u32 tran_mode);
void FCanDeInitialize(FCanCtrl *instance_p);
const FCanConfig *FCanLookupConfig(u32 instance_id);
void FCanIdMaskFilterDisable(FCanCtrl *instance_p);
void FCanIdMaskFilterEnable(FCanCtrl *instance_p);
FError FCanIdMaskFilterSet(FCanCtrl *instance_p, FCanIdMaskConfig *id_mask_p);
#endif